package com.qitmiaojie.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qitmiaojie.controller.utils.GeoResult;
import com.qitmiaojie.controller.utils.Result;
import com.qitmiaojie.pojo.Geocode;
import com.qitmiaojie.pojo.Leave;
import com.qitmiaojie.pojo.StudentSteam;
import com.qitmiaojie.pojo.dto.Examine;
import com.qitmiaojie.pojo.dto.LeaveRecord;
import com.qitmiaojie.pojo.dto.StudentStream;
import com.qitmiaojie.pojo.geography.Feature;
import com.qitmiaojie.pojo.geography.Geometry;
import com.qitmiaojie.service.LeaveService;
import com.qitmiaojie.mapper.LeaveMapper;
import com.qitmiaojie.service.StudentService;
import com.qitmiaojie.utils.GetCoordination;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 *
 */
@Service
@Slf4j
public class LeaveServiceImpl extends ServiceImpl<LeaveMapper, Leave>
    implements LeaveService{
    @Value("${yuankun.city}")
    private String city; //济南市
    @Value("${yuankun.province}")
    private String province;     //  province: 山东省
    private String today= DateUtil.today();//今日日期
    @Value("${excel.download}")
    private String path;
    @Autowired
    private LeaveMapper leaveMapper;
    @Autowired
    private StudentService studentService;
    @Autowired
    private GetCoordination getCoordination; //高德地图api
    @Value("${yuankun.longitude}")
    private Double longitude;
    @Value("${yuankun.laitude}")
    private Double laitude;


    private final static String []times= {"00:00","03:00","06:00","09:00","12:00","15:00","18:00","21:00","24:00"};
    /**
     * 今日流动
     * @return
     */
    @Override
    public Result getStudentStream() {
        StudentSteam studentSteam = new StudentSteam(
                findSchoolLeave(today), findCityLeave(today,city), findProvinceLeave(today,province), findSchoolEnter(today));
        return Result.success(studentSteam);
    }

    @Override
    public Result getLastWeek() {
        String today= DateUtil.today();
        Date date=DateUtil.parse(today);
        log.info("当前 日期为{}",date);
        String lastWeek[]=new String[7];
        int j = 6;
        for (int i = 0; i < 7; i++) {
            lastWeek[i]  = DateUtil.format(DateUtil.offsetDay(date, -i), "yyyy-MM-dd");
            j--;
            log.info("往后推的日期为{}",lastWeek[i]);
        }
        StudentStream studentStreams[]=new StudentStream[7];
        Integer SchoolLeave[]=new Integer[7];
        Integer CityLeave[]=new Integer[7];
        Integer ProvinceLeave[]=new Integer[7];
        Integer SchoolEnter[]=new Integer[7];
        for (int i=0;i<7;i++){
            studentStreams[i]=new StudentStream(findSchoolLeave(lastWeek[i]),findCityLeave(lastWeek[i],city)
                    ,findProvinceLeave(lastWeek[i],province),findSchoolEnter(lastWeek[i]));
            SchoolLeave[i]=studentStreams[i].getSchoolLeave();
            CityLeave[i]=studentStreams[i].getCityLeave();
            ProvinceLeave[i]=studentStreams[i].getProvinceLeave();
            SchoolEnter[i]=studentStreams[i].getSchoolEnter();
        }
        Map<String,Object> map=new HashMap<>();
        map.put("SchoolLeave",SchoolLeave);
        map.put("CityLeave",CityLeave);
        map.put("ProvinceLeave",ProvinceLeave);
        map.put("SchoolEnter",SchoolEnter);
        map.put("LastWeek",lastWeek);
        return Result.success(map);
    }

    @Override
    public Result getPage(String name, String id, String examine, Integer currentPage, Integer size) {
        log.info(id);
        Map<String,Object> map=new HashMap<>();
        map.put("Name",name);
        map.put("Id",id);
        map.put("Examine",examine);
        map.put("start",(currentPage-1)*size);
        map.put("end",currentPage*size);
        Result result=new Result();
        Map<Object, Object> ResMap = MapUtil.builder()
                .put("data",null)
                .put("TotalCount", 0)
                .build();
        Integer TotalCount=leaveMapper.FindAllLeaveRecordCount(map);
        int start = (currentPage-1)*size;
        int end = currentPage*size;

        /*ResMap.replace("TotalCount",);*/
        List<LeaveRecord> recordList = leaveMapper.selectByPage(name,id,examine,start,end);
        ResMap.replace("data",recordList);
        ResMap.replace("TotalCount",TotalCount);
        return Result.success(ResMap);
    }

    @Override
    public Result getByGeography(String address) {
        Geocode geocode = getCoordination.getCoordinate(address);
        if(geocode==null){
            return new Result(300,"查询失败！",null);
        }
            return Result.success("查询成功！",geocode);
    }

    @Override
    public Result addExamine(Examine examine) {
        Integer id = leaveMapper.insertExamine(examine); //返回自增id
        Geocode geocode=getCoordination.getCoordinate(examine.getDestination());
      /*  Map<String,Object> map=new HashMap<>();
        map.put("leave_id",examine.getId());
        map.put("location",geocode.getLocation());
        Integer count=leaveMapper.AddFeature(map);*/
        Result result = new Result();
        if(id == null||id == 0){
            result.setObject(null);
            result.setMsg("请假申请失败");
            result.setStateCode(300);
        }else{
            result.setObject(null);
            result.setMsg("请假申请成功");
            result.setStateCode(200);
        }
        return result;
    }

    @Override
    public Result updateExamineById(Integer id, String examine) {
        LambdaUpdateWrapper<Leave> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Leave::getId,id);
        updateWrapper.set(Leave::getExamine,examine);
        boolean update = update(updateWrapper);
        return Result.success("修改成功",null);
    }

    @Override
    public Result updateLeave(Leave leave) {
        boolean flag = updateById(leave);
        if ("已出校".equals(leave.getStatues()) || "是".equals(leave.getIsLeave())){
            Geocode geocode=getCoordination.getCoordinate(leave.getDestination());
            Map<String,Object> map=new HashMap<>();
            map.put("leave_id",leave.getId());
            map.put("location",geocode.getLocation());
            Integer count=leaveMapper.AddFeature(map);
        }
        return Result.success("修改成功！",null);
    }

    @SneakyThrows
    @Override
    public void downLoadExcelAll(HttpServletResponse response) {

        List<LeaveRecord> recordList = leaveMapper.selectLeaveRecordAll();

// 定义输出文件名称
        String excelName = "学生请假信息导出-" +  UUID.randomUUID().toString() +  ".xlsx";

// 导出本地文件
        File file = new File(path + excelName);
        log.info(file.toString());

// 写入本地文件中，此处用自动适应列宽的策略
        EasyExcelFactory.write(file, LeaveRecord.class).
                registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("sheet名称").doWrite(recordList);


// web页面导出下载
   /*     String excelName = "学生请假信息导出-" +  UUID.randomUUID().toString() +  ".xlsx";
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + excelName + ".xlsx");
        //数据

        // 这里需要设置不关闭流 数据在response.OutPutStream里面  前端需要res.data
        EasyExcel.write(response.getOutputStream(), LeaveRecord.class).autoCloseStream(Boolean.FALSE).sheet("模板")
                .doWrite(recordList);*/

        /*response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf8");
        response.setHeader("Content-disposition", "attachment;filename=" + excelName );
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            EasyExcel.write(outputStream, LeaveRecord.class)
                    .sheet("sheet1")
                    .doWrite(recordList);
        } catch (IOException e) {
            e.printStackTrace();
        }*/



    }

    @Override
    public Result getDayTime() {
       /* Integer []in=new Integer[8];
        Integer []out=new Integer[8];
        for (int i = 0; i < 8; i++) {
            String startTime = today+ " " +times[i];
            String endTime = today+ " " +times[i+1];

            in[i]=leaveMapper.selectDayTimeIn(startTime,endTime);
            LambdaQueryWrapper<Leave> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.between(Leave::getStartdate,startTime,endTime);
            in[i] = count(queryWrapper);
            out[i]=leaveMapper.selectDayTimeOut(startTime,endTime);

        }*/
        Integer []in=new Integer[8];
        Integer []out=new Integer[8];
        for (int i = 0; i < 8; i++) {
            String today= DateUtil.today();
         /*   *//* in[i]=leaveMapper.selectDayTimeIn(startTime,endTime);*//*
            LambdaQueryWrapper<Leave> inQueryWrapper = new LambdaQueryWrapper<>();
            inQueryWrapper.between(Leave::getStartdate,startTime,endTime);
            *//*where enddate >= #{timestart} and startdate < #{timeend}*//*
            inQueryWrapper.ge(Leave::getEnddate,startTime);
            inQueryWrapper.lt(Leave::getStartdate,endTime);
            in[i] = count(inQueryWrapper);
            LambdaQueryWrapper<Leave> outQueryWrapper = new LambdaQueryWrapper<>();
            *//*startdate >= #{timestart} and startdate < #{timeend}")*//*
            outQueryWrapper.ge(Leave::getStartdate,startTime);
            outQueryWrapper.lt(Leave::getStartdate,endTime);
            out[i]=count(outQueryWrapper);
            System.out.println("in = " + in[i].toString() +"    out=  " +  out[i].toString());*/
            String timestart=today+ " " +times[i];
            String timeend=today+ " " +times[i+1];
            leaveMapper.FindDayTimeIn(timestart,timeend,today);
            String liketoday = "%" + today + "%";
            in[i]=leaveMapper.FindDayTimeIn(timestart,timeend,liketoday);
            out[i]=leaveMapper.FindDayTimeOut(timestart,timeend,liketoday);

        }
        Map<String,Object> map=new HashMap<>();
        map.put("in",out);
        map.put("out",in);
        return Result.success(map);
    }

    @Override
    public GeoResult getGeographyJson() {
        GeoResult geoResult=new GeoResult();
        geoResult.setType("FeatureCollection");
        Feature feature=new Feature();
        LambdaQueryWrapper<Feature> queryWrapper = new LambdaQueryWrapper<>();
        List<Feature> list= leaveMapper.selectAllFeature();
        List<String> stringList=leaveMapper.selectAllCoordinates();
        list = list.stream().map(new Function<Feature, Feature>() {
            int i = 0;
            @Override
            public Feature apply(Feature feature) {
                Double[][] doubleList = new Double[2][2];
                doubleList[0][0] = longitude;
                doubleList[0][1] = laitude;
                doubleList[1][0] = Double.parseDouble(stringList.get(i).split(",")[0]);
                //System.out.println(stringList.get(i).split(",")[0]);
                doubleList[1][1] = Double.parseDouble(stringList.get(i).split(",")[1]);
                //System.out.println(stringList.get(i).split(",")[1]);
                //System.out.println(doubleList);
                Geometry geometry = feature.getGeometry();
                geometry.setCoordinates(doubleList);
                feature.setGeometry(geometry);
                i++;
                return feature;
            }
        }).collect(Collectors.toList());
        geoResult.setFeatures(list);
        return geoResult;
    }


    private Integer findSchoolEnter(String today) {
        LambdaQueryWrapper<Leave> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Leave::getEnddate,today);
        queryWrapper.eq(Leave::getExamine,"已审批");
        return count(queryWrapper);
    }

    private Integer findProvinceLeave(String today,String province) {
        LambdaQueryWrapper<Leave> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Leave::getStartdate,today);
        queryWrapper.notLike(Leave::getDestination,province);
        queryWrapper.eq(Leave::getExamine,"已审批");
        return count(queryWrapper);
    }

    private Integer findSchoolLeave(String today){

        LambdaQueryWrapper<Leave> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Leave::getStartdate,today);
        queryWrapper.eq(Leave::getExamine,"已审批");
        return count(queryWrapper);
    }
    private Integer findCityLeave(String today,String city){
        LambdaQueryWrapper<Leave> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Leave::getStartdate,today);
        queryWrapper.eq(Leave::getExamine,"已审批");
        queryWrapper.notLike(Leave::getDestination,city);
        return count(queryWrapper);
    }
}




